package com.jdwx.opengl.kotlin

import java.util.*


sealed class Expr{
    fun a(){}
}
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()

fun eval(expr: Expr): Double = when(expr) {
    is Const -> expr.number
    is Sum -> eval(expr.e1) + eval(expr.e2)
    NotANumber -> Double.NaN
    // 不再需要 `else` 子句，因为我们已经覆盖了所有的情况
}
class Box<T>(t: T) {
    var value = t
}

interface Source<out T> {
    fun nextT(): T
}

fun demo(strs: Source<String>) {
    val objects: Source<Any> = strs // 这个没问题，因为 T 是一个 out-参数
    // ……
}

fun <T> sort(list: List<T>) {


}
class Outer {
    private val bar: Int = 1
    class Nested {
        fun foo() = 2
    }
}
class Outer1 {
    private val bar: Int = 1
    inner class Nested {
        fun foo() = 2
        fun foo2() = bar
    }
}
enum class Direction {
    NORTH, SOUTH, WEST, EAST
}
enum class Color  constructor(val rgb: Int) {
    RED(0xFF0000),
    GREEN(0x00FF00),
    BLUE(0x0000FF)
}
enum class RGB { RED, GREEN, BLUE }
enum class ConsoleColor(var argb : Int){
    RED(0xFF0000){
        override fun print() {
            println("我是枚举常量 RED ")
        }
    },
    WHITE(0xFFFFFF){
        override fun print() {
            println("我是枚举常量 WHITE ")
        }
    },
    BLACK(0x000000){
        override fun print() {
            println("我是枚举常量 BLACK ")
        }
    },
    GREEN(0x00FF00){
        override fun print() {
            println("我是枚举常量 GREEN ")
        }
    };

    abstract fun print()
}
class MyClass {
    companion object Factory {
        fun create(): MyClass = MyClass()
    }
    var ji = 10
}

class MyClass1 {
    companion object {
        fun create(): MyClass = MyClass()
    }
    var ji = 10
}
class MyClass3 {
    companion object Named { }
    var ji = 10
}


class MyClass2 {
    companion object { }
    var ji = 10
}

val y = MyClass2


interface Factory<T> {
    fun create(): T
}

class MyClass4 {
    companion object : Factory<MyClass4> {
        override fun create(): MyClass4 = MyClass4()
    }
    var ji = 10

    var counter = 0 // 注意：这个初始器直接为幕后字段赋值
        set(value) {
            if (value >= 0) field = value
        }
}

class Person1(var gender:Gender){
    var name:String = ""
        set(value) {
            field = when(gender){
                Gender.MALE -> "Jake.$value"
                Gender.FEMALE -> "Rose.$value"
            }
        }
}
enum class Gender{
    MALE,
    FEMALE
}


fun main(){
//    println( eval( Const( 10.0 ) ) )
//    var box = Box( 10 );
//    println( box.value )
//    sort(listOf(1, 2, 3)) // OK。Int 是 Comparable<Int> 的子类型
//    sort(listOf(HashMap<Int, String>())) // 错误：HashMap<Int, String> 不是 Comparable<HashMap<Int, String>> 的子类型
//
//    val demo = Outer.Nested().foo() // == 2
//
//    var color:Color=Color.BLUE
//
//    println(Color.values())
//    println(Color.valueOf("RED"))
//    println(color.name)
//    println(color.ordinal)

    //printAllValues<RGB>() // 输出 RED, GREEN, BLUE
    var a = listOf(1,3,4).joinToString(",")
    println( a )

    println( ConsoleColor.BLACK.print() )

    //println(enumValues<Color>().joinToString { it.name })
    val instance = MyClass.create()
    instance.ji
    val x = MyClass1.Companion
    x.create().ji

    val x2 = MyClass
    x2.create().ji

    var v = MyClass4.create().ji

    val f: Factory<MyClass4> = MyClass4

    f.create().ji
    MyClass4.create().ji


    // 性别MALE
    var person = Person1(Gender.MALE)
    person.name="Love"
    println("打印结果:${person.name}")
    //性别：FEMALE
    var person2 = Person1(Gender.FEMALE)
    person2.name="Love"
    println("打印结果:${person2.name}")

    fun double(x: Int = 3,y:Int=1): Int {
        return 2 * x * y
    }

    println( double( x=10,y=10 ) )


    fun foo(vararg strings: String) {
        println( strings[0] )
    }

    foo(strings = *arrayOf("a", "b", "c"))

    fun printHello(name: String?): Unit {
        if (name != null)
            println("Hello ${name}")
        else
            println("Hi there!")
        // `return Unit` 或者 `return` 是可选的
        return
    }


    fun double(x: Int): Int = x * 2
    fun double2(x: Int) = x * 2

    println( double(1) )

    println( double2(1) )


    fun <T> asList(vararg ts: T): List<T> {
        val result = ArrayList<T>()
        for (t in ts) // ts is an Array
            result.add(t)
        return result
    }

    println( asList( listOf(1,2,3) ).joinToString("--") )

    var a12 = 1.shl(2)

    println( a12 )

    class MyStringCollection {
        infix fun add(s: String) {
            println("s="+s)
            /*……*/ }

        fun build() {
            this add "abc"   // 正确
            add("abc")       // 正确
            //add "abc"        // 错误：必须指定接收者
        }
    }

    var l = MyStringCollection()

    l.add( "baijinhao" )

    l add "xiaobai"

    val eps = 1E-10 // "good enough", could be 10^-15

    //尾递归函数
    tailrec fun findFixPoint(x: Double = 1.0): Double
            = if (Math.abs(x - Math.cos(x)) < eps) x else findFixPoint(Math.cos(x))

    fun findFixPoint(): Double {
        var x = 1.0
        while (true) {
            val y = Math.cos(x)
            if (Math.abs(x - y) < eps) return x
            x = Math.cos(x)
        }
    }


    val items = listOf(3, 4,5, 6, 7)

    // Lambdas 表达式是花括号括起来的代码块。
    items.fold(0, {
        // 如果一个 lambda 表达式有参数，前面是参数，后跟“->”
        acc: Int, i: Int ->
        print("acc = $acc, i = $i, ")
        val result = acc + i
        println("result = $result")
        // lambda 表达式中的最后一个表达式是返回值：
        result
    })


    // lambda 表达式的参数类型是可选的，如果能够推断出来的话：
    val joinedToString = items.fold("s:", { acc, i -> acc + "-" + i
    })


    val product = items.fold(1, Int::times)

    println("joinedToString = $joinedToString")
    println("product = $product")


    var a333 = { acc: Int, i: Int  ->
        println( "acc={$acc+1}" )
    }


    println( a333(1,10) )

    var abj = {
        x: Int ->  x * 2

    }(10)

    println("abj="+ abj )

    run { println(42) }//42

   var a11 =   fun(s: String): Int { return s.toInt() ?: 0 }

    println( a11("1" ) )

}
